package com.kotodama.application.cqrs.handlers.tenant;

import com.kotodama.application.cqrs.commands.tenant.CreateTenantCommand;
import com.kotodama.application.cqrs.handlers.CommandHandler;
import com.kotodama.domain.entities.Tenant;
import com.kotodama.domain.enums.TenantStatus;
import com.kotodama.domain.events.DomainEventPublisher;
import com.kotodama.domain.events.tenant.TenantCreatedEvent;
import com.kotodama.domain.exceptions.TenantNameAlreadyExistsException;
import com.kotodama.domain.repositories.TenantRepository;
import com.kotodama.domain.services.TenantDomainService;
import com.kotodama.domain.valueobjects.TenantName;
import com.kotodama.infrastructure.cache.TenantCacheService;
import com.kotodama.application.service.validation.TenantValidationService;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

/**
 * 创建租户命令处理器
 * 集成缓存和规则引擎
 */
@Component
public class CreateTenantCommandHandler implements CommandHandler<CreateTenantCommand, Tenant> {

    private final TenantRepository tenantRepository;
    private final DomainEventPublisher eventPublisher;
    private final TenantDomainService tenantDomainService;
    private final TenantCacheService tenantCacheService;
    private final TenantValidationService tenantValidationService;

    public CreateTenantCommandHandler(TenantRepository tenantRepository,
            DomainEventPublisher eventPublisher,
            TenantDomainService tenantDomainService,
            TenantCacheService tenantCacheService,
            TenantValidationService tenantValidationService) {
        this.tenantRepository = tenantRepository;
        this.eventPublisher = eventPublisher;
        this.tenantDomainService = tenantDomainService;
        this.tenantCacheService = tenantCacheService;
        this.tenantValidationService = tenantValidationService;
    }

    @Override
    @Transactional
    public Tenant handle(CreateTenantCommand command) {
        // 创建租户名称值对象
        TenantName tenantName = new TenantName(command.getName());

        // 检查租户名称是否已存在（先查缓存）
        var cachedExists = tenantCacheService.getTenantExists(command.getName());
        boolean nameExists = cachedExists.orElseGet(() -> {
            boolean exists = tenantRepository.existsByName(command.getName());
            tenantCacheService.cacheTenantExists(command.getName(), exists);
            return exists;
        });

        if (nameExists) {
            throw new TenantNameAlreadyExistsException(command.getName());
        }

        // 执行领域服务验证
        tenantDomainService.validateTenantCreation(command.getName());

        // 创建租户实体
        Tenant tenant = new Tenant(tenantName, TenantStatus.INACTIVE);

        // 执行业务规则验证
        var validationResult = tenantValidationService.validateTenantCreation(tenant);
        if (!validationResult.isValid()) {
            throw new IllegalArgumentException("租户创建验证失败: " +
                    String.join(", ", validationResult.getErrors()));
        }

        // 保存租户
        Tenant savedTenant = tenantRepository.save(tenant);

        // 预热缓存
        tenantCacheService.warmUpTenantCache(savedTenant);

        // 发布领域事件
        TenantCreatedEvent event = new TenantCreatedEvent(
                command.getTenantId(),
                savedTenant.getId(),
                savedTenant.getName().getValue(),
                savedTenant.getStatus());
        eventPublisher.publish(event);

        return savedTenant;
    }

    @Override
    public Class<CreateTenantCommand> getSupportedCommandType() {
        return CreateTenantCommand.class;
    }
}